package cn.tworice.common.utils;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.*;

/**
 * 具有时效性的HashMap
 * 可以设置具有时效的键值对
 * @author 二饭[tworice@sina.cn][2022/1/7 11:24]
 * @version 1.0
 */
public class AgingMap<K,V>  implements Serializable {

    private static final long serialVersionUID = 2756845907061754852L;

    /**
     * 默认最大长度
     * @author 二饭[tworice@sina.cn][2022/1/7 12:46]
     */
    private static final int maxLength = 10;

    /**
     * 用于存储数据的HashMap集合
     * @author 二饭[tworice@sina.cn][2022/1/7 11:04]
     */
    private transient HashMap<K,V> map=null;

    //    private transient FixedPriorityQueue<Object> queue;
    private transient HashMap<K, Timer> timerMap = null;

    /**
     * 用于初始化AgingMap
     * 初始化用于存储数据的HashMap
     * 初始化用于设置时效的Timer
     * @author 二饭[tworice@sina.cn][2022/1/7 11:09]
     */
    public AgingMap(){
        map = new HashMap<>();
        timerMap = new HashMap<>();
//        queue = new FixedPriorityQueue<>();
    }

    /**
     * 添加长期有效的键值对
     * @param key Map集合的键
     * @param value Map集合的值
     * @return V 返回存储成功后的值
     * @author 二饭[tworice@sina.cn][2022/1/7 11:07]
     */
    public V put(K key,V value){
        return map.put(key, value);
    }

    /**
     * 添加有时效的键值对
     * @param key Map集合的键
     * @param value Map集合的值
     * @param ms 该键值对的时效
     * @return V 返回存储成功后的值
     * @author 二饭[tworice@sina.cn][2022/1/7 11:07]
     */
    public V put(K key,V value,long ms){
        if(refuse()){
            put(key, value);
            aging(key, ms);
            return value;
        }else {
            return null;
        }
    }

    
    /**
     * 设置时效结束后删除相应Key
     * @param key Map集合的键
     * @param ms 规定该Map集合键值对的时效
     * @author 二饭[tworice@sina.cn][2022/1/6 22:57]
     */
    public void aging(K key, long ms) {
        Timer timer = new Timer();
        timerMap.put(key, timer);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                map.remove(key);
                timer.cancel();
                timer.purge();
                timerMap.remove(key);
            }
        },ms);
    }

    /**
     * 删除指定的Key
     * 清除指定的Timer
     * @author 二饭[tworice@sina.cn][2022/1/7 17:47]
     */
    public void remove(K key){
        if(timerMap.containsKey(key)){
            timerMap.get(key).cancel();
            timerMap.get(key).purge();
            timerMap.remove(key);
        }
        map.remove(key);
    }

    /**
     * 通过键值获取值
     * @param key Map的键
     * @return V 返回Map集合存储的值
     * @author 二饭[tworice@sina.cn][2022/1/7 11:05]
     */
    public V get(K key){
        return map.get(key);
    }

    /**
     * 判断是否存在该键值对
     * @param key Map集合的键
     * @param value Map集合的值
     * @author 二饭[tworice@sina.cn][2022/1/7 15:17]
     */
    public boolean exist(K key,V value){
        return map.containsKey(key) && map.get(key).equals(value);
    }


    /**
     * 拒绝策略
     * 当到达最高容积后拒绝再添加元素
     * @author 二饭[tworice@sina.cn][2022/1/7 13:12]
     */
    private boolean refuse(){
        if(timerMap.size()>=maxLength){
            return false;
        }
        return true;
    }

    /**
     * 获取数据Map
     * @return
     */
    public Map<K, V> getMap(){
        return this.map;
    }

    /**
     * 判断key是否存在
     * @param key 数据Map的key
     * @return 返回是否存在
     */
    public boolean containsKey(K key){
        return map.containsKey(key);
    }

    /**
     * 如果存在则删除Key
     * @param key 数据Map的key
     */
    public void removeKey(K key){
        map.remove(key);
    }
    

}
